home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Examples / 3Dkit / Simple / SimpleCamera.m < prev    next >
Encoding:
Text File  |  1993-01-10  |  7.1 KB  |  194 lines

  1. #import <appkit/appkit.h>
  2. #import "SimpleCamera.h"
  3. #import "SimpleShape.h"
  4.  
  5. /* SimpleCamera -- by Bill Bumgarner 6/1/92
  6.  *                   with assistance from Dave Springer.
  7.  *
  8.  * SimpleCamera demonstrates the creation of a very simple 3Dkit scene 
  9.  * that has mouse control via the N3DRotator class, supports dumping RIB 
  10.  * code to a file, contains light sources (ambient light and a point light), 
  11.  * has a surface shader, supports both WireFrame and SmoothSolid rendering, 
  12.  * and has a single custom N3DShape that generates a Torus (or teapot).
  13.  *
  14.  * Simple.app was created as an example of using the 3Dkit.  Parts of it
  15.  * come from Teapot.app by Dave Springer (see SimpleShape.m).
  16.  *
  17.  *  You may freely copy, distribute and reuse the code in this example.
  18.  *  NeXT disclaims any warranty of any kind, expressed or implied,
  19.  *  as to its fitness for any particular use.
  20.  */
  21.  
  22. @implementation SimpleCamera
  23. - initFrame:(const NXRect *) theRect
  24. {
  25.   // camera position points
  26.   // Note that the camera vector is in a left-handed coordinate system; this
  27.   // is the default for RenderMan.  In order to look at the front of the
  28.   // scene, you have to step backwards along the z-axis; in other words, you
  29.   // have to move the eye point negatively in z.  
  30.   RtPoint fromP = {0,0,-5.0}, toP = {0,0,0};
  31.  
  32.   // light position point
  33.   // Notice the "-0.75" z-coordinate.  This is because of the left-handed
  34.   // coordinate system.
  35.   RtPoint lFromP = {0.5,0.5,-0.75};
  36.  
  37.   // the various 3Dkit object id''s that we will initialize here
  38.   id ambientLight;
  39.   id aLight;
  40.   id aShader;
  41.   id aShape;
  42.  
  43.   // initialize camera and put it at (0,0,-5.0) looking at the origin (0,0,0)
  44.   // roll specifies the roll angle of the camera...
  45.   [super initFrame:theRect];
  46.   [self setEyeAt:fromP toward:toP roll:0.0];
  47.   
  48.   // create a shader that will shade surfaces with a simple matte surface.
  49.   aShader=[[N3DShader alloc] init];
  50.   // Generate a blue matte surface.
  51.   // This is slow on a monochrome system.
  52.   [aShader setUseColor:YES];
  53.   [aShader setColor:NX_COLORBLUE];
  54.   [(N3DShader *)aShader setShader:"matte"];
  55.   // Comment the previous line and uncomment the following lines to generate
  56.   // a texture-mapped surface.  The N3DShader object does all the necessary
  57.   // things to make a shader work properly: it sends all the Declare commands
  58.   // and a complete parameter string.  All you need to do is change the
  59.   // parameters you want with the -setShaderArg:fooValue: family of methods.
  60.   // When you compile your own shader, all the information about the arguments
  61.   // and their default values are stored in the .slo file, and the N3DShader
  62.   // object knows how to read them.
  63.   //[(N3DShader *)aShader setShader:"texmap"];
  64.   //[aShader setShaderArg:"texname"
  65.   //     stringValue:"/NextLibrary/Textures/pebbles.tx"];
  66.  
  67.   // initialize the world shape and set its shader to be aShader
  68.   aShape=[[SimpleShape alloc] init];
  69.   [(N3DShape *) aShape  setShader:aShader];
  70.   [[self setWorldShape:aShape] free]; // free the default world shape
  71.  
  72.   // create an ambientlight source.
  73.   ambientLight=[[N3DLight alloc] init];
  74.   [ambientLight makeAmbientWithIntensity:0.1];
  75.   [self addLight:ambientLight];
  76.   
  77.   // create a Point light and put it at (0.5, 0.5, -0.75) at 
  78.   // full intensity (1.0).
  79.   aLight=[[N3DLight alloc] init];
  80.   [aLight makePointFrom:lFromP intensity:1.0];
  81.   [self addLight:aLight];
  82.  
  83.   // create another Point light and put it at (-0.5, -0.5, -0.75) at 
  84.   // full intensity (1.0).
  85.   N3D_XComp( lFromP ) = -0.5;
  86.   N3D_YComp( lFromP ) = -0.5;
  87.   aLight=[[N3DLight alloc] init];
  88.   [aLight makePointFrom:lFromP intensity:1.0];
  89.   [self addLight:aLight];
  90.  
  91.   // set the surface type to generate smooth solids.  The mouseDown:
  92.   // method automatically drops to N3D_WireFrame whenever the user manipulates
  93.   // the scene via the mouse (see the mouseDown: implementation below).
  94.   // This must be done after the setWorldShape: method (or after any new shape
  95.   // is added to the hierarchy).
  96.   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
  97.  
  98.   // allocate and initialize the N3DRotator object that governs
  99.   // rotational control via the mouseDown: method
  100.   theRotator=[[N3DRotator alloc] initWithCamera:self];
  101.  
  102.   return self;
  103. }
  104.  
  105. - dumpRib:sender
  106. {
  107.   static id savePanel=nil;
  108.   NXStream *ts;
  109.   char buf[MAXPATHLEN+1];
  110.  
  111.   // initialize the savePanel, if it hasn''t been done so previously
  112.   if (!savePanel) {
  113.     savePanel=[SavePanel new];
  114.     [savePanel setRequiredFileType:"rib"];
  115.   }
  116.  
  117.   // run the savepanel.  
  118.   if([savePanel runModal]){
  119.     // returned w/pathname, open a stream and
  120.     ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
  121.     // process the file name for a custom display line such that
  122.     // "prman <<filename>>.rib" will put the resulting image somewhere
  123.     // predictably useful.
  124.     strcpy(buf, [savePanel filename]);
  125.     // remove the .rib extension from the path returned by the SavePanel
  126.     strrchr(buf,'.')[0]='\0';
  127.     // feed to NXPrintf to put in the custom Display command
  128.     NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
  129.     // then feed the rib code to the stream and
  130.     [self copyRIBCode:ts];
  131.     // save the stream to the file selected in the savepanel
  132.     NXSaveToFile(ts, [savePanel filename]);
  133.     // and close the stream (which also flushes it), also making sure
  134.     // that the allocated memory is freed.
  135.     NXCloseMemory(ts,NX_FREEBUFFER);
  136.   }
  137.   return self;
  138. }
  139.  
  140. #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
  141. - mouseDown:(NXEvent *)theEvent
  142. {
  143.   int                     oldMask;
  144.   NXPoint        oldMouse, newMouse, dMouse;
  145.   RtMatrix        rmat, irmat;
  146.  
  147.   // find out what axis of rotation the rotator should be constrained to
  148.   switch([rotoMatrix selectedRow]){
  149.   case 0: [theRotator setRotationAxis:N3D_AllAxes]; break;
  150.   case 1: [theRotator setRotationAxis:N3D_XAxis]; break;
  151.   case 2: [theRotator setRotationAxis:N3D_YAxis]; break;
  152.   case 3: [theRotator setRotationAxis:N3D_ZAxis]; break;
  153.   case 4: [theRotator setRotationAxis:N3D_XYAxes]; break;
  154.   case 5: [theRotator setRotationAxis:N3D_XZAxes]; break;
  155.   case 6: [theRotator setRotationAxis:N3D_YZAxes]; break;
  156.   }
  157.  
  158.   // track the mouse until a mouseUp event occurs, updating the display
  159.   // as tracking happens.
  160.   [self lockFocus];
  161.   oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
  162.   
  163.   // switch to the N3D_WireFrame surface type
  164.   [self setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES];
  165.   
  166.   oldMouse = theEvent->location;
  167.   [self convertPoint:&oldMouse fromView:nil];
  168.   while (1)
  169.   {
  170.     newMouse = theEvent->location;
  171.     [self convertPoint:&newMouse fromView:nil];
  172.     dMouse.x = newMouse.x - oldMouse.x;
  173.     dMouse.y = newMouse.y - oldMouse.y;
  174.     if (dMouse.x != 0.0 || dMouse.y != 0.0) {
  175.       [theRotator trackMouseFrom:&oldMouse to:&newMouse
  176.        rotationMatrix:rmat andInverse:irmat];
  177.       [worldShape concatTransformMatrix:rmat premultiply:NO];
  178.       [self display];
  179.     }
  180.     theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
  181.     if (theEvent->type == NX_MOUSEUP)
  182.       break;
  183.     oldMouse = newMouse;
  184.   }
  185.   // switch back to the N3D_SmoothSolids surface type
  186.   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];    
  187.   [self display];
  188.   [self unlockFocus];
  189.  
  190.   [window setEventMask:oldMask];
  191.   return self;
  192. }
  193. @end
  194.